/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 * \file     Sent.c                                                                                     *
 * \brief    This file mainly contains the external api for sent driver                                 *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2023/08/18     <td>1.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/
/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "SentEtimer.h"
#include "SchM_Sent.h"
#include "Det.h"
#include "Mcal_MemLibc.h"

/********************************************************************************************************
 *                                      Enumerated data types                                           *
 *******************************************************************************************************/
/**
 * @enum Sent_StateType
 * @brief Sent current driver status
*/
typedef enum {
    /* driver uninit status */
    SENT_STATUS_UNINIT = 0,
    /* driver initilized status */
    SENT_STATUS_INITED
} Sent_StateType;

/**
 * @enum Sent_ChannelStatusType
 * @brief Sent current channel status
*/
typedef enum {
    /* channel uninitialized */
    SENT_STATUS_UNINITIALIZED = 0,
    /* channel initialized */
    SENT_STATUS_INITIALIZED = 1,
    /* channel running status */
    SENT_STATUS_RUNNING = 2,
    /* channel stoped status */
    SENT_STATUS_STOPED = 3,
} Sent_ChannelStatusType;

/********************************************************************************************************
 *                                      Static variables                                                *
 *******************************************************************************************************/
#define SENT_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Sent_MemMap.h"
/* current sent driver init stat */
static Sent_StateType Sent_DriverState;
/* local saved Sent config pointer */
static const SentEtimer_ConfigType *Sent_ptrConfig;
/* physical to logic channel map */
static uint8 Phy2LogMap[TIMER_MODULE_NUMBER][LOCAL_CHANNEL_NUMBER];
/* all Sent channel status */
static Sent_ChannelStatusType Sent_ChnStaus[SENT_NUM_CHANNELS];

#define SENT_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Sent_MemMap.h"

/********************************************************************************************************
 *                                      internal fcuntion                                               *
 *******************************************************************************************************/
#define SENT_START_SEC_CODE
#include "Sent_MemMap.h"

static inline Std_ReturnType SentEtimer_ValidateCommon(SentEtimer_ChannelType Channel, uint8 ServiceID);
static inline Std_ReturnType SentEtimer_CheckStartReciever(SentEtimer_ChannelType Channel, uint8 ServiceID);
static inline Std_ReturnType SentEtimer_CheckStopReciever(SentEtimer_ChannelType Channel,uint8 ServiceID);
#if (SENT_DEINIT_API == STD_ON)
static inline Std_ReturnType SentEtimer_CheckDeInit(uint8 ServiceID);
#endif /** #if (SENT_DEINIT_API == STD_ON) */

/** *****************************************************************************************************
 * \brief This function check if the driver was initialized.
 *
 * \verbatim
 * Syntax             : static inline Std_ReturnType SentEtimer_ValidateCommon(
 *                                      SentEtimer_ChannelType Channel, uint8 ServiceID)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : Channel - The logic channel.
 *                      ServiceID - Function ID.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : validate result
 *
 * Description        : This function check if the driver was initialized.
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
static inline Std_ReturnType SentEtimer_ValidateCommon(SentEtimer_ChannelType Channel, uint8 ServiceID)
{
    Std_ReturnType RetVal = E_OK;

    if (SENT_STATUS_UNINIT == Sent_DriverState)
    {
        (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                                        (uint8)ServiceID, (uint8)SENTETIMER_E_UNINIT);
        RetVal = E_NOT_OK;
    }
    else if (Channel >= SENT_NUM_CHANNELS)
    {
        (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                                (uint8)ServiceID, (uint8)SENTETIMER_E_PARAM_CHANNEL);
        RetVal = E_NOT_OK;
    }
    else
    {
        /* do nothing */
    }

    return RetVal;
}

/* PRQA S 3206 EOF */
/** *****************************************************************************************************
 * \brief This function check the driver parameter.
 *
 * \verbatim
 * Syntax             : static inline Std_ReturnType SentEtimer_CheckStartReciever(
 *                                          SentEtimer_ChannelType Channel, uint8 ServiceID)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : Channel - The logic channel.
 *                      ServiceID - Function ID.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : validate result
 *
 * Description        : This function check the driver parameter.
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
static inline Std_ReturnType SentEtimer_CheckStartReciever(SentEtimer_ChannelType Channel, uint8 ServiceID)
{
    Std_ReturnType RetVal = E_OK;

    if (Sent_ChnStaus[Channel] == SENT_STATUS_UNINITIALIZED)
    {
#if (SENT_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                                (uint8)ServiceID, (uint8)SENTETIMER_E_CHAN_STATUS);
#endif
        RetVal = E_NOT_OK;
    }

    return RetVal;
}

/** *****************************************************************************************************
 * \brief This function check the parameter when stop the reciever
 *
 * \verbatim
 * Syntax             : static inline Std_ReturnType SentEtimer_CheckStopReciever(
 *                                          SentEtimer_ChannelType Channel, uint8 ServiceID)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : Channel - The logic channel.
 *                      ServiceID - Function ID.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : validate result
 *
 * Description        : This function check the parameter when stop the reciever
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
static inline Std_ReturnType SentEtimer_CheckStopReciever(SentEtimer_ChannelType Channel, uint8 ServiceID)
{
    Std_ReturnType RetVal = E_OK;

    if (Sent_ChnStaus[Channel] != SENT_STATUS_RUNNING)
    {
#if (SENT_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                                (uint8)ServiceID, (uint8)SENTETIMER_E_CHAN_STATUS);
#endif
        RetVal = E_NOT_OK;
    }

    return RetVal;
}

#if (SENT_DEINIT_API == STD_ON)
/** *****************************************************************************************************
 * \brief This function check the parameter when deinit the driver
 *
 * \verbatim
 * Syntax             : static inline Std_ReturnType SentEtimer_CheckDeInit(uint8 ServiceID)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : ServiceID - Function ID.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : validate result
 *
 * Description        : This function check the parameter when deinit the deinit driver
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
static inline Std_ReturnType SentEtimer_CheckDeInit(uint8 ServiceID)
{
    Std_ReturnType RetVal = E_OK;
    SentEtimer_ChannelType Channel;
    /* PRQA S 2877 1 */
    for (Channel = 0; Channel < SENT_NUM_CHANNELS; Channel++)
    {
        if (Sent_ChnStaus[Channel] == SENT_STATUS_RUNNING)
        {
#if (SENT_DEV_ERROR_DETECT == STD_ON)
            (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                                (uint8)ServiceID, (uint8)SENTETIMER_E_CHAN_STATUS);
#endif
            RetVal = E_NOT_OK;
        }
    }

    return RetVal;
}
#endif /** #if (SENT_DEINIT_API == STD_ON) */

/** *****************************************************************************************************
 * \brief This function initializes the driver.
 *
 * \verbatim
 * Syntax             : FUNC(void, SENT_CODE) SentEtimer_Init
 *                        (
 *                             P2CONST(SentEtimer_ConfigType, AUTOMATIC, SENT_APPL_CONST) ConfigPtr
 *                        )
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : ConfigPtr - Pointer to a selected configuration structure.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function initializes the driver.
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_Init(const SentEtimer_ConfigType *ConfigPtr)
{
    SentEtimer_ChannelType Channel;

    if (SENT_STATUS_UNINIT == Sent_DriverState)
    {
        if (NULL_PTR != ConfigPtr)
        {
            Sent_ptrConfig = ConfigPtr;
            SentEtimer_Ip_SetBaseAddr();
            /* PRQA S 2877 1 */
            for (Channel = 0; Channel < SENT_NUM_CHANNELS; Channel++)
            {
                SentEtimer_Ip_ChannelInit(Channel, &((*(Sent_ptrConfig->ptrChannelConfig))[Channel]));
                Phy2LogMap[(*(Sent_ptrConfig->ptrChannelConfig))[Channel].SentHwChannelConfig->u8TimerModule]\
                [(*(Sent_ptrConfig->ptrChannelConfig))[Channel].SentHwChannelConfig->u8HwChannel] = Channel;
                Sent_ChnStaus[Channel] = SENT_STATUS_INITIALIZED;
            }

            Sent_DriverState = SENT_STATUS_INITED;
        }
        else
        {
#if (SENT_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                        (uint8)SENTETIMER_INIT_ID, (uint8)SENTETIMER_E_PARAM_POINTER);
#endif /* SENT_DEV_ERROR_DETECT */
        }

    }
    else
    {
#if (SENT_DEV_ERROR_DETECT == STD_ON)
    (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                    (uint8)SENTETIMER_INIT_ID, (uint8)SENTETIMER_E_ALREADY_INITIALIZED);
#endif /* SENT_DEV_ERROR_DETECT */
    }
}

#if (SENT_DEINIT_API == STD_ON)
/** *****************************************************************************************************
 * \brief This function de-initializes the SENT module.
 *
 * \verbatim
 * Syntax             : void SentEtimer_DeInit(void)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function de-initializes the SENT module.
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_DeInit(void)
{
    SentEtimer_ChannelType Channel;

    if ((SENT_STATUS_INITED == Sent_DriverState) &&
        (E_OK == SentEtimer_CheckDeInit(SENTETIMER_DEINIT_ID)))
    {
        /* PRQA S 2877 1 */
        for (Channel = 0; Channel < SENT_NUM_CHANNELS; Channel++)
        {
            SentEtimer_Ip_ChannelDeInit(Channel, &((*(Sent_ptrConfig->ptrChannelConfig))[Channel]));
            Phy2LogMap[(*(Sent_ptrConfig->ptrChannelConfig))[Channel].SentHwChannelConfig->u8TimerModule]\
            [(*(Sent_ptrConfig->ptrChannelConfig))[Channel].SentHwChannelConfig->u8HwChannel] = 0u;
            Sent_ChnStaus[Channel] = SENT_STATUS_UNINITIALIZED;
        }

        Sent_ptrConfig = NULL_PTR;
        Sent_DriverState = SENT_STATUS_UNINIT;
    }

}
#endif /* SENT_DEINIT_API == STD_ON */

/** *****************************************************************************************************
 * \brief This function start the sent reciever.
 *
 * \verbatim
 * Syntax             : void SentEtimer_StartReciever(SentEtimer_ChannelType Channel)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function start the sent reciever.
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_StartReciever(SentEtimer_ChannelType Channel)
{
    if (E_OK == SentEtimer_CheckStartReciever(Channel, SENTETIMER_START_RECIEVER_ID))
    {
        if (E_OK == SentEtimer_ValidateCommon(Channel, SENTETIMER_START_RECIEVER_ID))
        {
            SentEtimer_Ip_StartReciever(Channel, (*(Sent_ptrConfig->ptrChannelConfig))[Channel].SentHwChannelConfig);
            Sent_ChnStaus[Channel] = SENT_STATUS_RUNNING;
        }
    }
}


/** *****************************************************************************************************
 * \brief This function stop the sent reciever.
 *
 * \verbatim
 * Syntax             : void SentEtimer_StopReciever(SentEtimer_ChannelType Channel)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : None
 *
 * Parameters (in)    : None
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function stop the sent reciever.
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_StopReciever(SentEtimer_ChannelType Channel)
{
    if (E_OK == SentEtimer_CheckStopReciever(Channel, SENTETIMER_STOP_RECIEVER_ID))
    {
        if (E_OK == SentEtimer_ValidateCommon(Channel, SENTETIMER_STOP_RECIEVER_ID))
        {
            SentEtimer_Ip_StopReciever(Channel, (*(Sent_ptrConfig->ptrChannelConfig))[Channel].SentHwChannelConfig);
            Sent_ChnStaus[Channel] = SENT_STATUS_STOPED;
        }
    }
}

#define SENT_STOP_SEC_CODE
#include "Sent_MemMap.h"


#define SENT_START_SEC_CODE_FAST
#include "Sent_MemMap.h"
/** *****************************************************************************************************
 * \brief This function get the sent frame information
 *
 * \verbatim
 * Syntax             : boolean SentEtimer_GetFrameInfo(SentEtimer_ChannelType Channel,
 *                                                  uint32 *pError, SentEtimer_Frame *pFrameInfo)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : Channel - the logic channel
 *                      pError - frame error status
 *                      pFrameInfo - frame data information
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : TRUE:is newest message;
 *                      FALSE:is already read or not update data
 *
 * Description        : This function get the sent frame information
 *
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
boolean SentEtimer_GetFrameInfo(SentEtimer_ChannelType Channel, uint32 *pError, SentEtimer_Frame *pFrameInfo)
{
    boolean RetVal = FALSE;

    if (E_OK == SentEtimer_ValidateCommon(Channel, SENTETIMER_GET_FRAME_INFO_ID))
    {
        /* check the channel status */
        if (Sent_ChnStaus[Channel] == SENT_STATUS_RUNNING)
        {
            if ((NULL_PTR == pError) ||
                (NULL_PTR == pFrameInfo))
            {
#if (SENT_DEV_ERROR_DETECT == STD_ON)
                (void)Det_ReportError((uint16)SENTETIMER_MODULE_ID, (uint8)SENTETIMER_INSTANCE_ID,
                                (uint8)SENTETIMER_GET_FRAME_INFO_ID, (uint8)SENTETIMER_E_PARAM_POINTER);
#endif /* SENT_DEV_ERROR_DETECT */
            }
            else
            {
                SchM_Enter_Sent_SENT_EXCLUSIVE_AREA_00();
                RetVal = SentEtimer_FrameInfo[Channel].bReadFlag;
                *pError = SentEtimer_FrameInfo[Channel].eError;
                /* PRQA S 3200,0315 1 */
                Mcal_MemCpy(pFrameInfo, &SentEtimer_FrameInfo[Channel].FrameInfo, sizeof(SentEtimer_Frame));
                SentEtimer_FrameInfo[Channel].bReadFlag = FALSE;
                SchM_Exit_Sent_SENT_EXCLUSIVE_AREA_00();
            }
        }
    }
    return RetVal;
}

/** *****************************************************************************************************
 * \brief This function handle the interrupt service
 *
 * \verbatim
 * Syntax             : void SentEtimer_IrqCommon(uint8 eModule)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : eModule - sent hardware module
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : This function handle the interrupt service
 *
 * \endverbatim
 * Traceability       :
 *******************************************************************************************************/
void SentEtimer_IrqCommon(uint8 eModule)
{
    uint32 Irq_Status;
    uint8 j;
    uint8 HwChannel;
    uint8 Channel;
    Irq_Status = SentEtimer_Ip_GetInterrupt(eModule);

    for (j = 0u; j < 4u; j++) {
        /* check dma req interrupt */
        if (((Irq_Status >> (uint8)(20u + j)) & 0x1u) > 0u)
        {

            SentEtimer_Ip_ClearInterrupt(eModule, (uint8)(20U + j));
            HwChannel = j;
            Channel = Phy2LogMap[eModule][HwChannel];
            SentEtimer_Ip_Parse_Massage(Channel, &(*(Sent_ptrConfig->ptrChannelConfig))[Channel]);
        }
    }
}

#define SENT_STOP_SEC_CODE_FAST
#include "Sent_MemMap.h"

#ifdef __cplusplus
}
#endif

